package com.ycl.blog.interceptor;


import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Configuration
public class TimeOutInterceptor implements HandlerInterceptor {

    BlockingQueue<Thread> queue = new ArrayBlockingQueue<>(100);
    Map<Thread, Long> threadPeriod = new ConcurrentHashMap<>();
    long timeout = 5000;//5S则认为超时

    public TimeOutInterceptor() {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                //每5S判断下所有线程的时长，遇到没超时的线程，则停止，因为是顺序队列
                Thread thread = queue.peek();
                while (thread != null) {
                    Long period = threadPeriod.get(thread);
                    if (System.currentTimeMillis() - period >= timeout) {
                        queue.remove(thread);
                        threadPeriod.remove(thread);
                        thread.interrupt();
                        thread = queue.peek();
                    } else {
                        thread = null;
                    }
                }
            }
        }, 1000, timeout);
    }

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
//        log.info("============preHandle=========");

        Thread requestHandingThread = Thread.currentThread();
        threadPeriod.put(requestHandingThread, System.currentTimeMillis());
        queue.put(requestHandingThread);

        return true;
    }


    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler,
                           ModelAndView modelAndView) throws Exception {
//        log.info("============postHandle=========");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
                                Object handler, Exception e) throws Exception {
//        log.info("============afterCompletion=========");

        Thread requestHandingThread = Thread.currentThread();
        queue.remove(requestHandingThread);
        threadPeriod.remove(requestHandingThread);
    }
}
